document.addEventListener('DOMContentLoaded', () => {

    // 字母映射表
    const mapping = [
        'C',
        'D',
        'E',
        'F',
        'G',
        'A',
        'B',
    ];

    // 频率映射
    const frequencyMapping = {
        // 小字组
        'C3': 130.81,
        '#C3': 138.59,
        'D3': 146.83,
        '#D3': 155.56,
        'E3': 164.81,
        'F3': 174.61,
        '#F3': 184.99,
        'G3': 195.99,
        '#G3': 207.65,
        'A3': 220.00,
        '#A3': 233.08,
        'B3': 246.94,

        // 小字1组
        'C4': 261.63,
        '#C4': 277.18,
        'D4': 293.66,
        '#D4': 311.13,
        'E4': 329.63,
        'F4': 349.23,
        '#F4': 369.99,
        'G4': 391.99,
        '#G4': 415.30,
        'A4': 440.00,
        '#A4': 466.16,
        'B4': 493.88,

        // 小字2组
        'C5': 523.25,
        '#C5': 554.37,
        'D5': 587.33,
        '#D5': 622.25,
        'E5': 659.25,
        'F5': 698.46,
        '#F5': 739.99,
        'G5': 783.99,
        '#G5': 830.61,
        'A5': 880.00,
        '#A5': 932.33,
        'B5': 987.77,
    };

    // 音频上下文
    const ctx = new AudioContext();

    // 创建一组键盘
    function createPianoGroup(parent, frequencies, options) {
        // const gap = 6;                  // 沟槽尺寸
        // const whiteWidth = 60;          // 白键宽度
        // const whiteHeight = 300;        // 白键高度
        // const blackWidth = 40;          // 黑键宽度
        // const blackHeight = 200;        // 黑键高度
        options = options || {};
        const { gap = 6, whiteWidth = 54, whiteHeight = 300, blackWidth = 40, blackHeight = 200 } = options;


        // 黑键频率
        const blackFrequencies = frequencies.filter(e => e.startsWith('#'));
        // 白健频率
        const whiteFrequencies = frequencies.filter(e => !e.startsWith('#'));

        // 最底下层背景
        const container = document.createElement('div');        
        container.style.display = 'flex';
        container.style.gap = `${gap}px`;
        container.style.position = 'relative';

        // 白键容器
        const whiteList = [];
        for (let i=0; i<7; i++) {
            whiteList.push(document.createElement('div'));
        }
        // 黑键容器
        const blackList = [];
        for (let i=0; i<5; i++) {
            blackList.push(document.createElement('div'));
        }

        // 处理白键的样式
        for (let i=0; i<7; i++) {
            const item = whiteList[i];
            item.style.width = `${whiteWidth}px`;
            item.style.height = `${whiteHeight}px`;
            item.style.backgroundColor = '#fff';
            item.style.userSelect = 'none';
            item.style.cursor = 'pointer';

            item.style.display = 'flex';
            item.style.justifyContent = 'center';
            item.style.alignItems = 'flex-end';

            item.className = 'p-item white';
            // 创建一个span元素，用于标识字母
            const span = document.createElement('span');
            span.textContent = mapping[i];
            span.style.fontSize = '20px';
            span.style.fontWeight = 'bold';

            item.appendChild(span);

            // 处理点击样式以及播放逻辑
            const frequency = frequencyMapping[whiteFrequencies[i]];
            item.addEventListener('click', function() {
                this.classList.add('active');
                setTimeout(() => {
                    this.classList.remove('active');
                }, 100);

                playSound(frequency, 200);
            });

            // 添加到container中
            container.appendChild(item);

        }

        // offset值（偏移量）
        const offset = whiteWidth - (blackWidth - gap) / 2;
        // base值（基准值）
        let base = 0;
        // 处理黑键的样式以及播放逻辑
        for (let i=0; i<5; i++) {
            const item = blackList[i];
            item.style.width = `${blackWidth}px`;
            item.style.height = `${blackHeight}px`;
            item.style.backgroundColor = '#000';
            item.style.userSelect = 'none';
            item.style.cursor = 'pointer';
            item.style.position = 'absolute';
            item.style.top = '0px';

            item.className = 'p-item black';

            // 计算left值
            const left = base + offset;
            item.style.left = `${left}px`;
            // item.style.left = `0px`;

            // 更新base值
            if (i===1) {
                base = 2 * (whiteWidth + gap) + base;
            } else {
                base = whiteWidth + gap + base;
            }

            // 处理点击样式
            const frequency = frequencyMapping[blackFrequencies[i]];
            item.addEventListener('click', function() {
                this.classList.add('active');
                setTimeout(() => {
                    this.classList.remove('active');
                }, 100);

                playSound(frequency, 200);
            });

            // 添加到container中
            container.appendChild(item);
        }


        // 将container添加到parent中
        parent.appendChild(container);
    }

    // 播放音频
    function playSound(frequency, duration) {
        // 1. 音频上下文
        // const ctx = new AudioContext();
        // 2. 振荡器
        const oscillator = ctx.createOscillator();
        // 2.1 设置声音频率
        oscillator.frequency.setValueAtTime(frequency, ctx.currentTime);
        // 2.2 设置声音音色
        // oscillator.type = 'sine';                   
        oscillator.type = 'square';                 
        // oscillator.type = 'sawtooth';               
        // oscillator.type = 'triangle';               
        // 3. 增益节点
        const gainNode = ctx.createGain();
        // 3.1 设置音量
        gainNode.gain.setValueAtTime(0, ctx.currentTime);
        gainNode.gain.linearRampToValueAtTime(1, ctx.currentTime+0.02);
        // 4. 连接
        oscillator.connect(gainNode); 
        gainNode.connect(ctx.destination);                  // 4.1 增益节点连接外部音频设备
        // 5. 播放
        oscillator.start();
        // 6. 停止
        setTimeout(() => {
            oscillator.stop();
            oscillator.disconnect();
            gainNode.disconnect();
        }, duration);
    }

    function main() {
        // 小字组
        createPianoGroup(document.body, [
            'C3',
            '#C3',
            'D3',
            '#D3',
            'E3',
            'F3',
            '#F3',
            'G3',
            '#G3',
            'A3',
            '#A3',
            'B3',
        ]);
        // 小字1组
        createPianoGroup(document.body, [
            'C4',
            '#C4',
            'D4',
            '#D4',
            'E4',
            'F4',
            '#F4',
            'G4',
            '#G4',
            'A4',
            '#A4',
            'B4',
        ]);
        // 小字2组
        createPianoGroup(document.body, [
            'C5',
            '#C5',
            'D5',
            '#D5',
            'E5',
            'F5',
            '#F5',
            'G5',
            '#G5',
            'A5',
            '#A5',
            'B5',
        ]);
    }

    main();
});